#pragma once
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <unordered_map>
#include <time.h>
#include <functional>
#include <memory>
#include "Log.hpp"
#include "TcpServer.hpp"
#include "Session.hpp"

static const std::string SEP = "\r\n";
static const std::string kvSEP = ": ";
static const std::string suffixSEP = ".";
static const std::string urlSEP = "?";
static const std::string wwwroot = "wwwroot";
static const std::string defaultWWW = "index.html";
static const std::string defaultSuffix = ".html";
static const std::string httpVersion = "HTTP/1.0";

class HttpResponse;
class HttpRequest;
using func_t = std::function<std::shared_ptr<HttpResponse>(std::shared_ptr<HttpRequest>)>;

class HttpRequest
{
public:
    HttpRequest()
        : _blankLine(SEP), _path(wwwroot)
    {
    }
    bool DeSerializaHelper(std::string &in)
    {
        // 读取请求行
        int pos = in.find(SEP);
        if (pos == std::string::npos)
            return false;
        _reqLine = in.substr(0, pos);
        in.erase(0, pos + SEP.size());
        // 读取请求报头
        // flag为false表示未读到空行
        bool flag = false;
        while ((pos = in.find(SEP)) != std::string::npos)
        {
            std::string tmp = in.substr(0, pos);
            in.erase(0, pos + SEP.size());

            // 如果为空，说明读到了空行
            if (tmp.empty())
            {
                flag = true;
                break;
            }
            _headers.emplace_back(tmp);
        }
        if (!flag)
            return false;
        _content = in;
        return true;
    }
    bool ParseReqLine()
    {
        std::stringstream ss(_reqLine);
        ss >> _method >> _url >> _httpVersion;
        // 如果为空，有问题
        if (_method.empty() || _url.empty() || _httpVersion.empty())
            return false;

        std::string prefix = "Cookie: ";
        for (auto& line : _headers)
        {
            std::string cookie;
            if(strncmp(line.c_str(), prefix.c_str(), prefix.size()) == 0)
            {
                cookie = line.substr(prefix.size());
                _cookies.emplace_back(cookie);
                break;
            }
        }
        prefix = "sessionid=";
        for (auto& cookie : _cookies)
        {
            std::string sessionID;
            if(strncmp(cookie.c_str(), prefix.c_str(), prefix.size()) == 0)
            {
                _sessionID = cookie.substr(prefix.size());
                break;
            }
        }
        

        // 处理路径
        _path += _url;
        if (_path.back() == '/')
            _path += defaultWWW;

        return true;
    }
    bool ParseHeadlers()
    {
        for (auto &str : _headers)
        {
            auto pos = str.find(kvSEP);
            // 不是完整的报头
            if (pos == std::string::npos)
                return false;

            _kvMap[str.substr(0, pos)] = str.substr(pos + kvSEP.size());
        }
        return true;
    }
    void Print()
    {
        std::cout << "\033[1;42;33m" << _reqLine << "\033[0m" << std::endl;
        for (auto &str : _headers)
            std::cout << "\033[1;47;34m" << str << "\033[0m" << std::endl;
        std::cout << _blankLine;
        std::cout << "\033[4;47;30m" << _content << "\033[0m" << std::endl;

        std::cout << "\033[1;47;46m" << "method : " << _method << "\033[0m" << std::endl;
        std::cout << "\033[1;47;46m" << "url : " << _url << "\033[0m" << std::endl;
        std::cout << "\033[1;47;46m" << "httpVersion : " << _httpVersion << "\033[0m" << std::endl;
        std::cout << "\033[1;47;46m" << "path : " << _path << "\033[0m" << std::endl;

        // std::cout << "\033[1;47;46m" << ;
        // std::cout << "\033[0m";

        // std::cout << "\033[1;47;44m";
        // for (auto& [k, v] : _kvMap)
        // {
        //     std::cout << k << "-----" << v << std::endl;
        // }
        // std::cout << "\033[0m";
    }
    bool DeSerializa(std::string &in)
    {
        DeSerializaHelper(in);
        ParseReqLine();
        ParseHeadlers();

        return true;
    }
    std::string Url()
    {
        return _url;
    }
    std::string SessionID()
    {
        return _sessionID;
    }
    std::string Path()
    {
        return _path;
    }

    ~HttpRequest()
    {
    }

private:
    std::string _reqLine;
    std::vector<std::string> _headers;
    std::string _blankLine;
    std::string _content;

    std::string _sessionID;
    std::vector<std::string> _cookies;
    std::string _method;
    std::string _url;
    std::string _path; // 路径
    std::string _httpVersion;
    std::unordered_map<std::string, std::string> _kvMap;
};

class HttpResponse
{
public:
    HttpResponse()
        : _blankLine(SEP), _httpVersion(httpVersion)
    {
    }
    void AddStatusLine(int code, const std::string &desc)
    {
        _code = code;
        _descript = desc;
    }
    void AddHeadler(const std::string &k, const std::string &v)
    {
        _kvMap[k] = v;
    }
    void AddContent(const std::string &text)
    {
        _content = text;
    }
    std::string Serializa()
    {
        std::string ret;
        _statusLine = _httpVersion + " " + std::to_string(_code) + " " + _descript + SEP;
        for (auto &[k, v] : _kvMap)
        {
            _headers.emplace_back(k + kvSEP + v + SEP);
        }

        ret += _statusLine;
        for (auto &str : _headers)
            ret += str;
        ret += _blankLine;
        ret += _content;
        return ret;
    }
    ~HttpResponse()
    {
    }

private:
    std::string _statusLine;
    std::vector<std::string> _headers;
    std::string _blankLine;
    std::string _content;

    std::string _httpVersion;
    int _code;
    std::string _descript;
    std::unordered_map<std::string, std::string> _kvMap;
};

class Factory
{
public:
    static std::shared_ptr<HttpRequest> CreateHttpRequest()
    {
        return std::make_shared<HttpRequest>();
    }
    static std::shared_ptr<HttpResponse> CreateHttpResponse()
    {
        return std::make_shared<HttpResponse>();
    }
};

class HttpServer
{
public:
    HttpServer(uint16_t port)
    {
        _tsvr = std::make_unique<TcpServer>(port, std::bind(&HttpServer::HandlerRequest, this, std::placeholders::_1));
        _sessionManager = std::make_unique<SessionManager>();
    }

    void Run()
    {
        _tsvr->Loop();
    }

    std::string HandlerRequest(std::string request)
    {
        std::cout << "\033[1;47;30m" << request << "\033[0m";

        auto req = Factory::CreateHttpRequest();
        req->DeSerializa(request);
        auto response = Factory::CreateHttpResponse();

        static int NO = 0;
        std::cout << "url : " << req->Url() << std::endl;
        std::cout << "session ID : " << req->SessionID() << std::endl;
        if(req->Url() == "/login")
        {
            std::string sessionID = req->SessionID();
            //需要进行注册
            if(sessionID.empty())
            {
                std::string user = "user-" + std::to_string(++NO);
                session_sptr ss = std::make_shared<Session>(user, "logined");
                sessionID = _sessionManager->AddSession(ss);
                LOG(INFO, "%s 被添加, ID : %s\n", user.c_str(), sessionID.c_str());

                response->AddHeadler("Set-Cookie", "sessionid=" + sessionID + ";");

            }
        }
        else
        {
            std::string sessionID = req->SessionID();
            if(!sessionID.empty())
            {
                session_sptr ss = _sessionManager->GetSession(sessionID);
                if(ss != nullptr)
                    LOG(INFO, "%s 正在活跃...\n", ss->_userName.c_str());
                else
                    LOG(INFO, "cookie %s 已过期\n", sessionID.c_str());
            }
        }


        response->AddStatusLine(200, "OK");
        response->AddContent("<html><body><h1>hello world!!</h1></body></html>");

        return response->Serializa();
    }
    ~HttpServer()
    {
    }

private:
    std::unique_ptr<TcpServer> _tsvr;
    std::unique_ptr<SessionManager> _sessionManager;
};